package main

import (
    "bytes"
    "context"
    "encoding/base64"
    "encoding/json"
    "fmt"
    "github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
    "github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
    "io"
    "log"
    "math"
    "math/rand"
    "net/http"
    "os"
    "time"
)

// TIP <p>To run your code, right-click the code and select <b>Run</b>.</p> <p>Alternatively, click
// the <icon src="AllIcons.Actions.Execute"/> icon in the gutter and select the <b>Run</b> menu item from here.</p>

// 定义请求体的结构
type RequestData struct {
    Base64Image string `json:"base64_image"`
}

// 定义响应体的结构
type ResponseData struct {
    SomImageBase64    string          `json:"som_image_base64"`
    ParsedContentList []ParsedContent `json:"parsed_content_list"`
    Latency           float64         `json:"latency"`
}

// 定义响应体中ParsedContentList字段的子结构
type ParsedContent struct {
    Type          string    `json:"type"`
    Bbox          []float64 `json:"bbox"`
    Interactivity bool      `json:"interactivity"`
    Content       string    `json:"content"`
    Source        string    `json:"source"`
}

// 发送POST请求的函数
func sendPostRequest(apiURL string, base64Image string) ([]byte, error) {
    // 创建请求体
    requestData := RequestData{
        Base64Image: base64Image,
    }

    imageDataRes := make([]byte, 0)

    // 将请求体转换为JSON
    jsonData, err := json.Marshal(requestData)
    if err != nil {
        return imageDataRes, fmt.Errorf("无法将请求体转换为JSON: %v", err)
    }

    // 创建HTTP请求
    req, err := http.NewRequest("POST", apiURL, bytes.NewBuffer(jsonData))
    if err != nil {
        return imageDataRes, fmt.Errorf("无法创建HTTP请求: %v", err)
    }

    // 设置请求头
    req.Header.Set("Content-Type", "application/json")

    // 发送HTTP请求
    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        return imageDataRes, fmt.Errorf("无法发送HTTP请求: %v", err)
    }
    defer resp.Body.Close()

    // 检查响应状态码
    if resp.StatusCode != http.StatusOK {
        return imageDataRes, fmt.Errorf("HTTP请求失败，状态码: %d", resp.StatusCode)
    }

    // 输出成功信息
    // 读取响应体
    bodyBytes, err := io.ReadAll(resp.Body)
    if err != nil {
        return imageDataRes, fmt.Errorf("无法读取响应体: %v", err)
    }

    // 解析响应体中的JSON数据
    var responseData ResponseData
    err = json.Unmarshal(bodyBytes, &responseData)
    if err != nil {
        return imageDataRes, fmt.Errorf("无法解析响应体: %v", err)
    }

    // 解码Base64图片数据
    imageData, err := base64.StdEncoding.DecodeString(responseData.SomImageBase64)
    if err != nil {
        return imageDataRes, fmt.Errorf("无法解码Base64图片数据: %v", err)
    }

    // 生成随机文件名
    rand.NewSource(time.Now().UnixNano())
    fileName := fmt.Sprintf("./img/image_%d.png", rand.Intn(10000))

    // 保存图片文件
    err = os.WriteFile(fileName, imageData, 0644)
    if err != nil {
        return imageDataRes, fmt.Errorf("无法保存图片文件: %v", err)
    }

    // 输出成功信息
    fmt.Printf("图片已保存为: %s\n", fileName)

    for i := range responseData.ParsedContentList {
        for j := range responseData.ParsedContentList[i].Bbox {
            if j%2 == 0 {
                // screen height
                responseData.ParsedContentList[i].Bbox[j] = math.Round(responseData.ParsedContentList[i].Bbox[j] * 1080)
            } else {
                // screen width
                responseData.ParsedContentList[i].Bbox[j] = math.Round(responseData.ParsedContentList[i].Bbox[j] * 1920)
            }
        }
    }

    fmt.Println("解析结果:", (responseData.ParsedContentList))

    return imageData, nil
}

func main() {
    img := openImg()

    // println(img)

    // 定义API URL
    apiURL := "http://127.0.0.1:34569/parse/"
    // 调用发送POST请求的函数
    imageData, err := sendPostRequest(apiURL, img)
    if err != nil {
        fmt.Printf("发送POST请求时出错: %v\n", err)
    }

    upload_img("image_1.png", imageData)
}

func openImg() string {
    // 定义图片的路径
    imgPath := "./img/004.png"

    // 读取图片文件
    file, err := os.Open(imgPath)
    if err != nil {
        log.Fatalf("无法打开文件: %v", err)
    }
    defer file.Close()

    // 读取文件内容
    imgBytes, err := io.ReadAll(file)
    if err != nil {
        log.Fatalf("无法读取文件: %v", err)
    }

    // 将图片内容转换为Base64编码
    base64Str := base64.StdEncoding.EncodeToString(imgBytes)

    // 输出Base64编码的字符串
    return base64Str
}

func upload_img(file_name string, file_body []byte) {

    region := "cn-shanghai"
    bucketName := "model-tmp-file"
    objectName := file_name

    provider := credentials.NewStaticCredentialsProvider("", "")
    // 加载默认配置并设置凭证提供者和区域
    cfg := oss.LoadDefaultConfig().
        WithCredentialsProvider(provider).
        WithRegion(region).WithEndpoint("oss-cn-shanghai.aliyuncs.com")

    // 创建OSS客户端
    client := oss.NewClient(cfg)

    // 填写要上传的本地文件路径和文件名称，例如 /Users/localpath/exampleobject.txt
    // localFile := file_path
    body := bytes.NewReader(file_body)
    // 创建上传对象的请求
    putRequest := &oss.PutObjectRequest{
        Bucket:       oss.Ptr(bucketName),      // 存储空间名称
        Key:          oss.Ptr(objectName),      // 对象名称
        StorageClass: oss.StorageClassStandard, // 指定对象的存储类型为标准存储
        Acl:          oss.ObjectACLPrivate,     // 指定对象的访问权限为私有访问
        // Metadata:     map[string]string{},
        Body: body,
    }

    // 执行上传对象的请求
    result, err := client.PutObject(context.TODO(), putRequest)
    if err != nil {
        log.Fatalf("failed to put object from file %v", err)
        return
    }

    // 打印上传对象的结果
    log.Printf("put object from file result:%#v\n", result)
    // 生成GetObject的预签名URL

    objreq := oss.GetObjectRequest{
        Bucket: oss.Ptr(bucketName),
        Key:    oss.Ptr(objectName),
    }

    presign_result, err := client.Presign(context.TODO(), &objreq, oss.PresignExpires(10*time.Minute))

    if err != nil {
        log.Fatalf("failed to get object presign %v", err)
    }

    log.Printf("request url:%v\n", presign_result.URL)

}
